#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "RPiHeliTCPClient.h"
#include <QSettings>
#include <unistd.h>
#include "devicedialog.h"
#include "rpi_sensors.h"
//#include "domitem.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    client = new RPIHelicopterClient();
    connect(ui->connectBtn,SIGNAL(clicked()),this,SLOT(connectBtnPressed()));
    //connect(ui->steerSlider,SIGNAL(sliderMoved(int)),this,SLOT(steerTo(int)));
    //connect(ui->motorSlider,SIGNAL(sliderMoved(int)),this,SLOT(setMotorPower(int)));

    //connect(ui->steerSlider,SIGNAL(valueChanged(int)),this,SLOT(steerTo(int)));
    //connect(ui->motorSlider,SIGNAL(valueChanged(int)),this,SLOT(setMotorPower(int)));

    connect(ui->steerSpinBox,SIGNAL(valueChanged(int)),this,SLOT(steerTo(int)));
    connect(ui->motorSpinBox,SIGNAL(valueChanged(int)),this,SLOT(setMotorPower(int)));
    connect(ui->mbackward,SIGNAL(clicked()),this,SLOT(moveBackward()));
    connect(ui->mforwardBtn,SIGNAL(clicked()),this,SLOT(moveForward()));
    connect(client,SIGNAL(sendAccGui(double*)),this,SLOT(setAccXYZT(double*)));

    accelerometerW = new accelerometerWidget(this,client->accelerometer);
    accelerometerW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(accelerometerW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,accelerometerW);
    connect(client,SIGNAL(updateAccelerometer()),accelerometerW,SLOT(refreshContent()));


    gyroscopeW = new gyroscopeWidget(this,client->gyroscope);
    gyroscopeW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(gyroscopeW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,gyroscopeW);
    connect(client,SIGNAL(updateGyroscope()),gyroscopeW,SLOT(refreshContent()));

    compassW = new compassWidget(this,client->compass);
    compassW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(compassW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,compassW);
    connect(client,SIGNAL(updateCompass()),compassW,SLOT(refreshContent()));

    pressureW = new pressureWidget(this,client->pressure);
    pressureW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(pressureW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,pressureW);
    connect(client,SIGNAL(updateCompass()),pressureW,SLOT(refreshContent()));

    gpsW = new gpsWidget(this,client->gps);
    pressureW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(gpsW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,gpsW);
    connect(client,SIGNAL(updateGPS()),gpsW,SLOT(refreshContent()));

    ultrasonicSensoresW = new ultrasonicSensoresWidget(this,&client->ultrasonicSensors);
    ultrasonicSensoresW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(ultrasonicSensoresW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,ultrasonicSensoresW);
    connect(client,SIGNAL(updateUltrasonicSensors()),ultrasonicSensoresW,SLOT(refreshContent()));


    controlsW = new controlsWidget(this,&client->controls);
    controlsW->setAllowedAreas(Qt::AllDockWidgetAreas);
    ui->menuSensors->addAction(controlsW->toggleViewAction());
    //addDockWidget(Qt::LeftDockWidgetArea,controlsW);
    connect(client,SIGNAL(updateControls()),controlsW,SLOT(refreshContent()));

    connect(ui->actionE_xit,SIGNAL(triggered()),this,SLOT(close()));


    connect(ui->actionConnectS,SIGNAL(triggered()),this,SLOT(connectMBtnClicked()));
    connect(ui->actionDisconnet,SIGNAL(triggered()),this,SLOT(disconnectMBtnClicked()));


    connect(client,SIGNAL(connected()),this,SLOT(Connected()));
    connect(client,SIGNAL(disconnected()),this,SLOT(lostConnection()));
    connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError)));
    connect(ui->actionGyroscope,SIGNAL(triggered()),this,SLOT(configureGyroscopeMBtnClicked()));
    connect(ui->actionAccelerometer,SIGNAL(triggered()),this,SLOT(configureAccelerometerMBtnClicked()));
    connect(ui->actionCompass,SIGNAL(triggered()),this,SLOT(configureCompassMBtnClicked()));
    connect(ui->actionGPS,SIGNAL(triggered()),this,SLOT(configureGPSMBtnClicked()));
    connect(ui->actionPressure,SIGNAL(triggered()),this,SLOT(configurePressureMBtnClicked()));
    connect(ui->actionSave_Config,SIGNAL(triggered()),client,SLOT(saveConfig()));

    connect(ui->actionInsertControl,SIGNAL(triggered()),client,SLOT(requestControls()));

    connect(client,SIGNAL(updateControls()),controlsW,SLOT(refreshContent()));
    connect(controlsW,SIGNAL(controlUpdate(int)),client,SLOT(sendControl(int)));
    disconnectMBtnClicked();

    loadDockState();
}
#include <QMessageBox>
void MainWindow::socketError(QAbstractSocket::SocketError e) {
    QString messageText;
    switch (e) {
    case QAbstractSocket::ConnectionRefusedError : { messageText = "The connection was refused by the peer (or timed out)." ; break;}
    case QAbstractSocket::RemoteHostClosedError : { messageText = "The remote host closed the connection. Note that the client socket (i.e., this socket) will be closed after the remote close notification has been sent." ; break;}
    case QAbstractSocket::HostNotFoundError : { messageText = "The host address was not found." ; break;}
    case QAbstractSocket::SocketAccessError : { messageText = "The socket operation failed because the application lacked the required privileges." ; break;}
    case QAbstractSocket::SocketResourceError : { messageText = "The local system ran out of resources (e.g., too many sockets)." ; break;}
    case QAbstractSocket::SocketTimeoutError : { messageText = "The socket operation timed out." ; break;}
    case QAbstractSocket::DatagramTooLargeError : { messageText = "The datagram was larger than the operating system's limit (which can be as low as 8192 bytes)." ; break;}
    case QAbstractSocket::NetworkError : { messageText = "An error occurred with the network (e.g., the network cable was accidentally plugged out)." ; break;}
    case QAbstractSocket::AddressInUseError : { messageText = "The address specified to QAbstractSocket::bind() is already in use and was set to be exclusive." ; break;}
    case QAbstractSocket::SocketAddressNotAvailableError : { messageText = "The address specified to QAbstractSocket::bind() does not belong to the host." ; break;}
    case QAbstractSocket::UnsupportedSocketOperationError : { messageText = "The requested socket operation is not supported by the local operating system (e.g., lack of IPv6 support)." ; break;}
    case QAbstractSocket::ProxyAuthenticationRequiredError : { messageText = "The socket is using a proxy, and the proxy requires authentication." ; break;}
    case QAbstractSocket::SslHandshakeFailedError : { messageText = "The SSL/TLS handshake failed, so the connection was closed (only used in QSslSocket)" ; break;}
    case QAbstractSocket::UnfinishedSocketOperationError : { messageText = "Used by QAbstractSocketEngine only, The last operation attempted has not finished yet (still in progress in the background)." ; break;}
    case QAbstractSocket::ProxyConnectionRefusedError : { messageText = "Could not contact the proxy server because the connection to that server was denied" ; break;}
    case QAbstractSocket::ProxyConnectionClosedError : { messageText = "The connection to the proxy server was closed unexpectedly (before the connection to the final peer was established)" ; break;}
    case QAbstractSocket::ProxyConnectionTimeoutError : { messageText = "The connection to the proxy server timed out or the proxy server stopped responding in the authentication phase." ; break;}
    case QAbstractSocket::ProxyNotFoundError : { messageText = "The proxy address set with setProxy() (or the application proxy) was not found." ; break;}
    case QAbstractSocket::ProxyProtocolError : { messageText = "The connection negotiation with the proxy server failed, because the response from the proxy server could not be understood." ; break;}
    case QAbstractSocket::OperationError : { messageText = "An operation was attempted while the socket was in a state that did not permit it." ; break;}
    case QAbstractSocket::SslInternalError : { messageText = "The SSL library being used reported an internal error. This is probably the result of a bad installation or misconfiguration of the library." ; break;}
    case QAbstractSocket::SslInvalidUserDataError : { messageText = "Invalid data (certificate, key, cypher, etc.) was provided and its use resulted in an error in the SSL library." ; break;}
    case QAbstractSocket::TemporaryError : { messageText = "A temporary error occurred (e.g., operation would block and socket is non-blocking)." ; break;}
    case QAbstractSocket::UnknownSocketError : { messageText = "An unidentified error occurred." ; break;}


    }
    disconnectMBtnClicked();
    QMessageBox::warning(this,"Error TCP Connection",messageText,QMessageBox::Ok);

}

void MainWindow::saveDockState() {
    QSettings settings("RaspberryHelicopter","RaspberryHelicopterClient");
    settings.setValue("DockState",saveGeometry());
    //qDebug() <<saveGeometry();
}
void MainWindow::loadDockState() {
    QSettings settings("RaspberryHelicopter","RaspberryHelicopterClient");
    restoreGeometry(settings.value("DockState").toByteArray());
    qDebug() << settings.property("DockState").toByteArray();
}

#include <QMessageBox>
void MainWindow::closeEvent(QCloseEvent *event)
{
    //if (maybeSave()) {
    //    writeSettings();
    if ( QMessageBox::critical(this,"Exiting","Are you sure you wish to exit?",QMessageBox::Yes,QMessageBox::No) == QMessageBox::Yes  )
        {
        saveDockState();
        event->accept();
        accelerometerW->close();
        controlsW->close();
        gyroscopeW->close();
        gpsW->close();
        pressureW->close();
        compassW->close();
        ultrasonicSensoresW->close();

    } else {
        event->ignore();
    }
}

MainWindow::~MainWindow()
{

    delete ui;
    delete accelerometerW;
    delete gpsW;
    delete ultrasonicSensoresW;
    delete compassW;
    delete pressureW;
    delete gyroscopeW;
    delete controlsW;
    delete client;
}

void MainWindow::connectBtnPressed() {

}

void MainWindow::steerTo(int s) {
    client->steerTo(ui->steerSpinBox->value());
}
void MainWindow::setMotorPower(int p) {
    client->setMotorPower(ui->motorSpinBox->value());
}

void MainWindow::moveForward() {
    client->setMotorPower(80);
    usleep(400000);
    client->setMotorPower(ui->motorSpinBox->value());
}
void MainWindow::moveBackward() {
    client->setMotorPower(178);
    usleep(400000);
    client->setMotorPower(ui->motorSpinBox->value());
}

void MainWindow::setAccXYZT(double *z){


}

#include "connectdialog.h";

void MainWindow::connectMBtnClicked() {
    qDebug() << "connectClicked";
    ConnectDialog cDialog(this);

    int ret = cDialog.exec();

    if (ret == QDialog::Accepted) {

        client->connectToHost(
                    cDialog.serverName(),
                                         cDialog.serverPort());

    }
}

void MainWindow::unableToConnect() {}
void MainWindow::lostConnection() {}
void MainWindow::Connected() {

    ui->actionConnectS->setDisabled(true);
    ui->actionCompass->setEnabled(true);
    ui->actionGPS->setEnabled(true);
    ui->actionPressure->setEnabled(true);
    ui->actionGyroscope->setEnabled(true);
    ui->actionAccelerometer->setEnabled(true);
    ui->actionInsertControl->setEnabled(true);
    ui->actionInsertUltrasonicSenor->setEnabled(true);
    ui->actionRemoveControl->setEnabled(true);
    ui->actionRemoveUltrasonicSensor->setEnabled(true);


    QMessageBox::information(this,"Successful Connection","Successfully Connected",QMessageBox::Ok);
    client->pollDevices();
}


void MainWindow::disconnectMBtnClicked() {

    ui->actionDisconnet->setDisabled(true);
    ui->actionCompass->setDisabled(true);
    ui->actionGPS->setDisabled(true);
    ui->actionPressure->setDisabled(true);
    ui->actionGyroscope->setDisabled(true);
    ui->actionAccelerometer->setDisabled(true);
    ui->actionInsertControl->setDisabled(true);
    ui->actionInsertUltrasonicSenor->setDisabled(true);
    ui->actionRemoveControl->setDisabled(true);
    ui->actionRemoveUltrasonicSensor->setDisabled(true);
    ui->actionConnectS->setEnabled(true);

    client->disconnectFromHost();
}
void MainWindow::configureAccelerometerMBtnClicked(){
    qDebug() << "Accelerometer Button Clicked";
    DeviceDialog dialog(this,client->accelerometer->basicDevice(),0);
    qDebug() << "Dialog Execute";
    if (dialog.exec() == QDialog::Accepted) {
        qDebug() << "Accepted : ";
        client->sendXML(client->accelerometer->toXML(false,true));
    }
}


void MainWindow::configureGyroscopeMBtnClicked() {
    DeviceDialog dialog(this,client->gyroscope->basicDevice(),0);
    qDebug() << "Gyroscope";
    if (dialog.exec() == QDialog::Accepted) {
        client->sendXML(client->gyroscope->toXML(false,true));
        qDebug() << "send" << client->gyroscope->toXML(false,true);
    }
}
void MainWindow::configureCompassMBtnClicked() {
    DeviceDialog dialog(this,client->compass->basicDevice(),0);
    if (dialog.exec() == QDialog::Accepted) {
        client->sendXML(client->compass->toXML(false,true));
    }
}
void MainWindow::configurePressureMBtnClicked() {
    DeviceDialog dialog(this,client->pressure->basicDevice(),0);
    if (dialog.exec() == QDialog::Accepted) {
        client->sendXML(client->pressure->toXML(false,true));
    }

}
void MainWindow::configureGPSMBtnClicked() {
    DeviceDialog dialog(this,client->gps->basicDevice(),0);
    if (dialog.exec() == QDialog::Accepted) {
        client->sendXML(client->gps->toXML(false,true));
    }
}
void MainWindow::insertUltrasonicMBtnClicked() {}
void MainWindow::insertcontrolMBtnClicked() {}
void MainWindow::removeUltrasonicMBtnClicked() {}
void MainWindow::removecontrolMBtnClicked() {}

